package com.itheima.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.domain.Category;
import com.itheima.domain.Dish;
import com.itheima.domain.DishDTO;
import com.itheima.domain.DishFlavor;
import com.itheima.mapper.CategoryMapper;
import com.itheima.mapper.DishFlavorMapper;
import com.itheima.mapper.DishMapper;
import com.itheima.service.DishService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.List;

/**
* @Author yangshuai
* @Desc:菜品详情-业务实现
* @Date 2022-6-6 15:45:10
* @Version 1.0
**/
@Service
@Slf4j
public class DishServiceImpl  implements DishService {
    @Autowired
    private DishMapper dishMapper;
    @Autowired
    private CategoryMapper categoryMapper;
    @Autowired
    private DishFlavorMapper dishFlavorMapper;

    @Override
    public Page<Dish> page(Integer page, Integer pageSize, String name) {
        //1:校验参数
        if (page<1){
            page =1;
        }
        if(pageSize<1){
            pageSize=10;
        }
        //2:拼接查询条件
          //2.1:根据名称查询的时候是一个模糊的查询
        LambdaQueryWrapper<Dish> wrapper=new LambdaQueryWrapper<>();
        if (StringUtils.isNotBlank(name)){
            //菜品名称要是不为空,则就去菜品表中去查询,所以来一个条件查询
            wrapper.like(Dish::getName,name.trim());
        }
        //每页的菜品展示顺序,根据时间降序来排序
        wrapper.orderByDesc(Dish::getUpdateTime);
        //校验完分页后,对分页进行封装
        Page<Dish> dishPage = new Page<Dish>(page, pageSize);
        //3:都处理完后,去数据库中查询
        Page<Dish> pageResult = dishMapper.selectPage(dishPage,wrapper);
        //1.1 获取当前页结果集列表数据
/*        List<Dish> records = pageResult.getRecords();
        //1.2 遍历结果集列表
        for (Dish record : records) {
            //1.3 根据Dish对象中的categoryId，查询分类对象
            Long categoryId = record.getCategoryId();
            Category category = categoryMapper.selectById(categoryId);
            //1.4 获取分类对象中分类名称，复制给Dish菜品对象的categoryName字段
            if(category != null){
                String categoryName = category.getName();
                record.setCategoryName(categoryName);
            }
        }*/
        //4:封装返回结果,给controller层用
        return pageResult;
    }

    @Override
    public int save(DishDTO dishDTO) {
        //1:对参数进行校验(这里要校验的有很多,name,price,长度等,有的没有校验)
            //1.1:先定义一下影响的行数
        int row =0;
        if (dishDTO == null) {
            return row;
        }
        //2:校验完参数后,进行数据的新增,去数据库中新增数据
            //2.1:新增的是以前没有的,所以要先创建好
        Dish dish = new Dish();
            //2.2:有了对象后,把前端传的数据,cv到dish这个对象中
        BeanUtils.copyProperties(dishDTO,dish);
        //3:有了数据,则进行插入
         row = dishMapper.insert(dish);
         //3.1:新增数据的时候,要对数据进行校验.若新增失败,则返回一个row<1;
        if (row <1) {
            return  row;   }
         //4:新增菜品的时候,这个口味也要判断;判断这个口味在数据库中是否存在,若存在就执行新增操作(因为一个菜品会给顾客提供多个口味)
        List<DishFlavor> flavors = dishDTO.getFlavors();
        if (flavors == null) {
            return row;
        }
        //5:都一样了,也都校验了,现在就真正的插入成功了,但是由于口味要单独插入,这个获取菜品id,其实是专门为了口味来写的,从数据库表中可以看到,我要去添加口味是根据id来添加的,这个id也不能自动填充,所以只能手写了
        Long dishId = dish.getId();
        //6:遍历一下,去给我想要存的那个id新增口味
        for (DishFlavor flavor : flavors) {
            flavor.setDishId(dishId);
            //进行口味的新增
            dishFlavorMapper.insert(flavor);

        }
        return row;
    }

    @Override
    public DishDTO findById(Long id) {
        DishDTO dishDTO = new DishDTO();
        //1:校验参数
        if (id == null) {
            return null;
        }
        //2:校验完参数不为空就去数据库中查询呀,根据id去查询
        Dish dish = dishMapper.selectById(id);
            //2.1:查完也要去校验一下
        if (dish == null) {
            return null;
        }
        //3:若查到数据了,查到对应的菜品了;但是对口味的处理还没进行,根据菜品id去查询口味列表数据
        LambdaQueryWrapper<DishFlavor> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(DishFlavor::getDishId,id);
        //拿到了口味的id去数据库进行查询
        List<DishFlavor> dishFlavors = dishFlavorMapper.selectList(wrapper);
        if (dishFlavors == null) {
            return null;
        }
        //4:都拿到了后,要对数据进行回显呀,由于Dish中没有设计到口味的东西,而DishDTO中有所以拷贝一下
        BeanUtils.copyProperties(dish,dishDTO);
        //再去判断一下
        if (dishFlavors != null) {
            //口味不为空的话,把口味给dishDTO
            dishDTO.setFlavors(dishFlavors);

        }
        //最终把dishDTO返回给控制层
        return dishDTO;
    }
    @Transactional(rollbackFor = Throwable.class)
    @Override
    public int update(DishDTO dishDTO) {
        int row =0;
        //1:校验参数的参数有如下:
        //1.1需要校验菜品名称 是否重复、是否为NULL、是否符合菜品名称格式、长度
        //1.2需要校验菜品金额 是否为NULL、是否为数值类型，是否格式正确
        //1.3需要校验图片是否为NULL、是否为图片格式
        //1.4需要校验菜品描述长度
        if (dishDTO == null) {
            return row;
        }
        //2:都校验完了后,先对菜品进行修改
        Dish dish = new Dish();
        BeanUtils.copyProperties(dishDTO,dish);
        row = dishMapper.updateById(dish);
        if (row <1) {
            return row;
        }
        //3:单独修改口味;先删除,后添加
           //3.1:删除前,先去根据id去查一下哈
        LambdaQueryWrapper<DishFlavor> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(DishFlavor::getDishId,dish.getId());
        dishFlavorMapper.delete(wrapper);
        //3.2由于口味不是必须传入的,所以只有口味有的时候,才进行修改
        if (dishDTO.getFlavors() != null) {
            List<DishFlavor> flavors = dishDTO.getFlavors();
            for (DishFlavor flavor:flavors){
                flavor.setDishId(dish.getId());
                dishFlavorMapper.insert(flavor);
            }

        }

        return row;
    }
    @Transactional
    @Override
    public void updateStatusByIds(Integer status, Long[] ids) {
        //1:校验参数
        if (status == null) {
            return;
        }
        if (ids == null) {
            return;
        }
        //2:进行数据的查询,查到了再执行修改(这个批量的停售与起售,其实就是变相的修改,他要去数据库中修改状态,1是起售状态,0是停售状态)
        //这里他是根据status与ids来查询的
        /*LambdaQueryWrapper<Dish> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Dish::getId,ids);
        wrapper.eq(Dish::getStatus,status);*/
        LambdaUpdateWrapper<Dish> wrapper = new LambdaUpdateWrapper<>();
        wrapper.set(Dish::getStatus,status);
        wrapper.in(Dish::getId,ids);
        //3:执行修改操作
        Dish dish = new Dish();
        dishMapper.update(dish,wrapper);
    }

    @Override
    public int deleteByIds(Long[] ids) {
        //1:校验参数
       int row=0;
        if (ids == null) {
            return row;
        }
        //2:若是ids有了,则可以根据id去数据库中执行删除操作了(我的理解哈,你都要去数据库中删除了,都不要这条数据了,就根据id直接删,不用去查询出来在删了,有就删没有就不删呗)
        //这个方法就是根据id批量删除,因为是批量删除,这个id就是个集合
        row = dishMapper.deleteBatchIds(Arrays.asList(ids));
        return row;
    }

    @Override
    public List<Dish> findDishListByCategoryId(Long categoryId, String name) {
        List<Dish> dishList = null;
        //1.构建条件
        LambdaQueryWrapper<Dish> wrapper = new LambdaQueryWrapper<>();
        //1.1 如果菜品分类ID不为NULL,添加菜品分类条件
        if (categoryId != null){
            wrapper.eq(Dish::getCategoryId,categoryId);
        }
        //1.2 如果菜品名称不为NULL,添加菜品名称条件(模糊查询)
        if (name != null){
            wrapper.like(Dish::getName,name.trim());
        }
        //2.执行查询
        dishList = dishMapper.selectList(wrapper);
        return dishList;
    }
}
